home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlbsp / solidbsp.cpp < prev    next >
C/C++ Source or Header  |  2002-11-15  |  32KB  |  1,124 lines

  1. #include "bsp5.h"
  2.  
  3. //  FaceSide
  4. //  ChooseMidPlaneFromList
  5. //  ChoosePlaneFromList
  6. //  SelectPartition
  7.  
  8. //  CalcSurfaceInfo
  9. //  DivideSurface
  10. //  SplitNodeSurfaces
  11. //  RankForContents
  12. //  ContentsForRank
  13.  
  14. //  FreeLeafSurfs
  15. //  LinkLeafFaces
  16. //  MakeNodePortal
  17. //  SplitNodePortals
  18. //  CalcNodeBounds
  19. //  CopyFacesToNode
  20. //  BuildBspTree_r
  21. //  SolidBSP
  22.  
  23. //  Each node or leaf will have a set of portals that completely enclose
  24. //  the volume of the node and pass into an adjacent node.
  25.  
  26. int             g_maxnode_size = DEFAULT_MAXNODE_SIZE;
  27.  
  28. // =====================================================================================
  29. //  FaceSide
  30. //      For BSP hueristic
  31. // =====================================================================================
  32. static int      FaceSide(face_t* in, const dplane_t* const split)
  33. {
  34.     int             frontcount, backcount;
  35.     vec_t           dot;
  36.     int             i;
  37.     vec_t*          p;
  38.  
  39.     frontcount = backcount = 0;
  40.  
  41.     // axial planes are fast
  42.     if (split->type <= last_axial)
  43.     {
  44.         vec_t           splitGtEp = split->dist + ON_EPSILON;   // Invariant moved out of loop
  45.         vec_t           splitLtEp = split->dist - ON_EPSILON;   // Invariant moved out of loop
  46.  
  47.         for (i = 0, p = in->pts[0] + split->type; i < in->numpoints; i++, p += 3)
  48.         {
  49.             if (*p > splitGtEp)
  50.             {
  51.                 if (backcount)
  52.                 {
  53.                     return SIDE_ON;
  54.                 }
  55.                 frontcount = 1;
  56.             }
  57.             else if (*p < splitLtEp)
  58.             {
  59.                 if (frontcount)
  60.                 {
  61.                     return SIDE_ON;
  62.                 }
  63.                 backcount = 1;
  64.             }
  65.         }
  66.     }
  67.     else
  68.     {
  69.         // sloping planes take longer
  70.         for (i = 0, p = in->pts[0]; i < in->numpoints; i++, p += 3)
  71.         {
  72.             dot = DotProduct(p, split->normal);
  73.             dot -= split->dist;
  74.             if (dot > ON_EPSILON)
  75.             {
  76.                 if (backcount)
  77.                 {
  78.                     return SIDE_ON;
  79.                 }
  80.                 frontcount = 1;
  81.             }
  82.             else if (dot < -ON_EPSILON)
  83.             {
  84.                 if (frontcount)
  85.                 {
  86.                     return SIDE_ON;
  87.                 }
  88.                 backcount = 1;
  89.             }
  90.         }
  91.     }
  92.  
  93.     if (!frontcount)
  94.     {
  95.         return SIDE_BACK;
  96.     }
  97.     if (!backcount)
  98.     {
  99.         return SIDE_FRONT;
  100.     }
  101.  
  102.     return SIDE_ON;
  103. }
  104.  
  105. // =====================================================================================
  106. //  ChooseMidPlaneFromList
  107. //      When there are a huge number of planes, just choose one closest
  108. //      to the middle.
  109. // =====================================================================================
  110. static surface_t* ChooseMidPlaneFromList(surface_t* surfaces, const vec3_t mins, const vec3_t maxs)
  111. {
  112.     int             j, l;
  113.     surface_t*      p;
  114.     surface_t*      bestsurface;
  115.     vec_t           bestvalue;
  116.     vec_t           value;
  117.     vec_t           dist;
  118.     dplane_t*       plane;
  119.  
  120.     //
  121.     // pick the plane that splits the least
  122.     //
  123.     bestvalue = 6 * 8192 * 8192;
  124.     bestsurface = NULL;
  125.  
  126.     for (p = surfaces; p; p = p->next)
  127.     {
  128.         if (p->onnode)
  129.         {
  130.             continue;
  131.         }
  132.  
  133.         plane = &g_dplanes[p->planenum];
  134.  
  135.         // check for axis aligned surfaces
  136.         l = plane->type;
  137.         if (l > last_axial)
  138.         {
  139.             continue;
  140.         }
  141.  
  142.         //
  143.         // calculate the split metric along axis l, smaller values are better
  144.         //
  145.         value = 0;
  146.  
  147.         dist = plane->dist * plane->normal[l];
  148.         for (j = 0; j < 3; j++)
  149.         {
  150.             if (j == l)
  151.             {
  152.                 value += (maxs[l] - dist) * (maxs[l] - dist);
  153.                 value += (dist - mins[l]) * (dist - mins[l]);
  154.             }
  155.             else
  156.             {
  157.                 value += 2 * (maxs[j] - mins[j]) * (maxs[j] - mins[j]);
  158.             }
  159.         }
  160.  
  161.         if (value > bestvalue)
  162.         {
  163.             continue;
  164.         }
  165.  
  166.         //
  167.         // currently the best!
  168.         //
  169.         bestvalue = value;
  170.         bestsurface = p;
  171.     }
  172.  
  173.     if (!bestsurface)
  174.     {
  175.         for (p = surfaces; p; p = p->next)
  176.         {
  177.             if (!p->onnode)
  178.             {
  179.                 return p;                                  // first valid surface
  180.             }
  181.         }
  182.         Error("ChooseMidPlaneFromList: no valid planes");
  183.     }
  184.  
  185.     return bestsurface;
  186. }
  187.  
  188. // =====================================================================================
  189. //  ChoosePlaneFromList
  190. //      Choose the plane that splits the least faces
  191. // =====================================================================================
  192. static surface_t* ChoosePlaneFromList(surface_t* surfaces, const vec3_t mins, const vec3_t maxs)
  193. {
  194.     int             j;
  195.     int             k;
  196.     int             l;
  197.     surface_t*      p;
  198.     surface_t*      p2;
  199.     surface_t*      bestsurface;
  200.     vec_t           bestvalue;
  201.     vec_t           bestdistribution;
  202.     vec_t           value;
  203.     vec_t           dist;
  204.     dplane_t*       plane;
  205.     face_t*         f;
  206.  
  207.     //
  208.     // pick the plane that splits the least
  209.     //
  210. #define UNDESIREABLE_HINT_FACTOR 10000
  211. #define WORST_VALUE 100000000
  212.     bestvalue = WORST_VALUE;
  213.     bestsurface = NULL;
  214.     bestdistribution = 9e30;
  215.  
  216.     for (p = surfaces; p; p = p->next)
  217.     {
  218.         if (p->onnode)
  219.         {
  220.             continue;
  221.         }
  222.  
  223. #ifdef ZHLT_DETAIL
  224.         if (g_bDetailBrushes)
  225.         {
  226.             // AJM: cycle though all faces, and make sure none of them are detail
  227.             // if any of them are, this surface isnt to cause a bsp split
  228.             for (face_t* f = p->faces; f; f = f->next)
  229.             {
  230.                 if (f->contents == CONTENTS_DETAIL)
  231.                 {
  232.                     //Log("ChoosePlaneFromList::got a detial surface, skipping...\n");
  233.                     continue;
  234.                 }
  235.             }
  236.         }
  237. #endif
  238.         
  239.         plane = &g_dplanes[p->planenum];
  240.         k = 0;
  241.  
  242.         for (p2 = surfaces; p2; p2 = p2->next)
  243.         {
  244.             if (p2 == p)
  245.             {
  246.                 continue;
  247.             }
  248.             if (p2->onnode)
  249.             {
  250.                 continue;
  251.             }
  252.  
  253.             for (f = p2->faces; f; f = f->next)
  254.             {
  255.                 // Give this face (a hint brush fragment) a large 'undesireable' value, only split when we have to)
  256.                 if (f->facestyle == face_hint)
  257.                 {
  258.                     k += UNDESIREABLE_HINT_FACTOR;
  259.                     hlassert(k < WORST_VALUE);
  260.                     if (k >= WORST_VALUE)
  261.                     {
  262.                         Warning("::ChoosePlaneFromList() surface fragmentation undesireability exceeded WORST_VALUE");
  263.                         k = WORST_VALUE - 1;
  264.                     }
  265.                 }
  266.                 if (FaceSide(f, plane) == SIDE_ON)
  267.                 {
  268.                     k++;
  269.                     if (k >= bestvalue)
  270.                     {
  271.                         break;
  272.                     }
  273.                 }
  274.  
  275.             }
  276.             if (k > bestvalue)
  277.             {
  278.                 break;
  279.             }
  280.         }
  281.  
  282.         if (k > bestvalue)
  283.         {
  284.             continue;
  285.         }
  286.  
  287.         // if equal numbers, axial planes win, then decide on spatial subdivision
  288.  
  289.         if (k < bestvalue || (k == bestvalue && (plane->type <= last_axial)))
  290.         {
  291.             // check for axis aligned surfaces
  292.             l = plane->type;
  293.  
  294.             if (l <= last_axial)
  295.             {                                              // axial aligned                                                
  296.                 //
  297.                 // calculate the split metric along axis l
  298.                 //
  299.                 value = 0;
  300.  
  301.                 for (j = 0; j < 3; j++)
  302.                 {
  303.                     if (j == l)
  304.                     {
  305.                         dist = plane->dist * plane->normal[l];
  306.                         value += (maxs[l] - dist) * (maxs[l] - dist);
  307.                         value += (dist - mins[l]) * (dist - mins[l]);
  308.                     }
  309.                     else
  310.                     {
  311.                         value += 2 * (maxs[j] - mins[j]) * (maxs[j] - mins[j]);
  312.                     }
  313.                 }
  314.  
  315.                 if (value > bestdistribution && k == bestvalue)
  316.                 {
  317.                     continue;
  318.                 }
  319.                 bestdistribution = value;
  320.             }
  321.             //
  322.             // currently the best!
  323.             //
  324.             bestvalue = k;
  325.             bestsurface = p;
  326.         }
  327.     }
  328.  
  329.     return bestsurface;
  330. }
  331.  
  332. // =====================================================================================
  333. //  SelectPartition
  334. //      Selects a surface from a linked list of surfaces to split the group on
  335. //      returns NULL if the surface list can not be divided any more (a leaf)
  336. // =====================================================================================
  337. static surface_t* SelectPartition(surface_t* surfaces, const node_t* const node, const bool usemidsplit)
  338. {
  339.     int             i;
  340.     surface_t*      p;
  341.     surface_t*      bestsurface;
  342.  
  343.     //
  344.     // count surface choices
  345.     //
  346.     i = 0;
  347.     bestsurface = NULL;
  348.     for (p = surfaces; p; p = p->next)
  349.     {
  350.         if (!p->onnode)
  351.         {
  352. #ifdef ZHLT_DETAIL
  353.             if (g_bDetailBrushes)
  354.             {
  355.                 // AJM: cycle though all faces, and make sure none of them are detail
  356.                 // if any of them are, this surface isnt to cause a bsp split
  357.                 for (face_t* f = p->faces; f; f = f->next)
  358.                 {
  359.                     if (f->contents == CONTENTS_DETAIL)
  360.                     {
  361.                         //Log("SelectPartition::got a detial surface, skipping...\n");
  362.                         continue;
  363.                     }
  364.                 }
  365.             }
  366. #endif
  367.             i++;
  368.             bestsurface = p;
  369.         }
  370.     }
  371.  
  372.     if (i == 0)
  373.     {
  374.         return NULL;                                       // this is a leafnode
  375.     }
  376.  
  377.     if (i == 1)
  378.     {
  379.         return bestsurface;                                // this is a final split
  380.     }
  381.  
  382.     if (usemidsplit)
  383.     {
  384.         // do fast way for clipping hull
  385.         return ChooseMidPlaneFromList(surfaces, node->mins, node->maxs);
  386.     }
  387.     else
  388.     {
  389.         // do slow way to save poly splits for drawing hull
  390.         return ChoosePlaneFromList(surfaces, node->mins, node->maxs);
  391.     }
  392. }
  393.  
  394. // =====================================================================================
  395. //  CalcSurfaceInfo
  396. //      Calculates the bounding box
  397. // =====================================================================================
  398. static void     CalcSurfaceInfo(surface_t* surf)
  399. {
  400.     int             i;
  401.     int             j;
  402.     face_t*         f;
  403.  
  404.     hlassume(surf->faces != NULL, assume_ValidPointer);    // "CalcSurfaceInfo() surface without a face"
  405.  
  406.     //
  407.     // calculate a bounding box
  408.     //
  409.     for (i = 0; i < 3; i++)
  410.     {
  411.         surf->mins[i] = 99999;
  412.         surf->maxs[i] = -99999;
  413.     }
  414.  
  415.     for (f = surf->faces; f; f = f->next)
  416.     {
  417.         if (f->contents >= 0)
  418.         {
  419.             Error("Bad contents");
  420.         }
  421.         for (i = 0; i < f->numpoints; i++)
  422.         {
  423.             for (j = 0; j < 3; j++)
  424.             {
  425.                 if (f->pts[i][j] < surf->mins[j])
  426.                 {
  427.                     surf->mins[j] = f->pts[i][j];
  428.                 }
  429.                 if (f->pts[i][j] > surf->maxs[j])
  430.                 {
  431.                     surf->maxs[j] = f->pts[i][j];
  432.                 }
  433.             }
  434.         }
  435.     }
  436. }
  437.  
  438. // =====================================================================================
  439. //  DivideSurface
  440. // =====================================================================================
  441. static void     DivideSurface(surface_t* in, const dplane_t* const split, surface_t** front, surface_t** back)
  442. {
  443.     face_t*         facet;
  444.     face_t*         next;
  445.     face_t*         frontlist;
  446.     face_t*         backlist;
  447.     face_t*         frontfrag;
  448.     face_t*         backfrag;
  449.     surface_t*      news;
  450.     dplane_t*       inplane;
  451.  
  452.     inplane = &g_dplanes[in->planenum];
  453.  
  454.     // parallel case is easy
  455.  
  456.     if (inplane->normal[0] == split->normal[0]
  457.      && inplane->normal[1] == split->normal[1]
  458.      && inplane->normal[2] == split->normal[2])
  459.     {
  460.         if (inplane->dist > split->dist)
  461.         {
  462.             *front = in;
  463.             *back = NULL;
  464.         }
  465.         else if (inplane->dist < split->dist)
  466.         {
  467.             *front = NULL;
  468.             *back = in;
  469.         }
  470.         else
  471.         {                                                  // split the surface into front and back
  472.             frontlist = NULL;
  473.             backlist = NULL;
  474.             for (facet = in->faces; facet; facet = next)
  475.             {
  476.                 next = facet->next;
  477.                 if (facet->planenum & 1)
  478.                 {
  479.                     facet->next = backlist;
  480.                     backlist = facet;
  481.                 }
  482.                 else
  483.                 {
  484.                     facet->next = frontlist;
  485.                     frontlist = facet;
  486.                 }
  487.             }
  488.             goto makesurfs;
  489.         }
  490.         return;
  491.     }
  492.  
  493.     // do a real split.  may still end up entirely on one side
  494.     // OPTIMIZE: use bounding box for fast test
  495.     frontlist = NULL;
  496.     backlist = NULL;
  497.  
  498.     for (facet = in->faces; facet; facet = next)
  499.     {
  500.         next = facet->next;
  501.         SplitFace(facet, split, &frontfrag, &backfrag);
  502.         if (frontfrag)
  503.         {
  504.             frontfrag->next = frontlist;
  505.             frontlist = frontfrag;
  506.         }
  507.         if (backfrag)
  508.         {
  509.             backfrag->next = backlist;
  510.             backlist = backfrag;
  511.         }
  512.     }
  513.  
  514.     // if nothing actually got split, just move the in plane
  515. makesurfs:
  516.     if (frontlist == NULL)
  517.     {
  518.         *front = NULL;
  519.         *back = in;
  520.         in->faces = backlist;
  521.         return;
  522.     }
  523.  
  524.     if (backlist == NULL)
  525.     {
  526.         *front = in;
  527.         *back = NULL;
  528.         in->faces = frontlist;
  529.         return;
  530.     }
  531.  
  532.     // stuff got split, so allocate one new surface and reuse in
  533.     news = AllocSurface();
  534.     *news = *in;
  535.     news->faces = backlist;
  536.     *back = news;
  537.  
  538.     in->faces = frontlist;
  539.     *front = in;
  540.  
  541.     // recalc bboxes and flags
  542.     CalcSurfaceInfo(news);
  543.     CalcSurfaceInfo(in);
  544. }
  545.  
  546. // =====================================================================================
  547. //  SplitNodeSurfaces
  548. // =====================================================================================
  549. static void     SplitNodeSurfaces(surface_t* surfaces, const node_t* const node)
  550. {
  551.     surface_t*      p;
  552.     surface_t*      next;
  553.     surface_t*      frontlist;
  554.     surface_t*      backlist;
  555.     surface_t*      frontfrag;
  556.     surface_t*      backfrag;
  557.     dplane_t*       splitplane;
  558.  
  559.     splitplane = &g_dplanes[node->planenum];
  560.  
  561.     frontlist = NULL;
  562.     backlist = NULL;
  563.  
  564.     for (p = surfaces; p; p = next)
  565.     {
  566.         next = p->next;
  567.         DivideSurface(p, splitplane, &frontfrag, &backfrag);
  568.  
  569.         if (frontfrag)
  570.         {
  571.             if (!frontfrag->faces)
  572.             {
  573.                 Error("surface with no faces");
  574.             }
  575.             frontfrag->next = frontlist;
  576.             frontlist = frontfrag;
  577.         }
  578.         if (backfrag)
  579.         {
  580.             if (!backfrag->faces)
  581.             {
  582.                 Error("surface with no faces");
  583.             }
  584.             backfrag->next = backlist;
  585.             backlist = backfrag;
  586.         }
  587.     }
  588.  
  589.     node->children[0]->surfaces = frontlist;
  590.     node->children[1]->surfaces = backlist;
  591. }
  592.  
  593. // =====================================================================================
  594. //  RankForContents
  595. // =====================================================================================
  596. static int      RankForContents(const int contents)
  597. {
  598.     //Log("SolidBSP::RankForContents - contents type is %i ",contents);
  599.     switch (contents)
  600.     {
  601. #ifdef ZHLT_NULLTEX    // AJM
  602.     case CONTENTS_NULL:
  603.         //Log("(null)\n");
  604.         //return 13;
  605.         return -2;
  606. #endif
  607.  
  608.     case CONTENTS_EMPTY:
  609.         //Log("(empty)\n");
  610.         return 0;
  611.     case CONTENTS_WATER:
  612.         //Log("(water)\n");
  613.         return 1;
  614.     case CONTENTS_TRANSLUCENT:
  615.         //Log("(traslucent)\n");
  616.         return 2;
  617.     case CONTENTS_CURRENT_0:
  618.         //Log("(current_0)\n");
  619.         return 3;
  620.     case CONTENTS_CURRENT_90:
  621.         //Log("(current_90)\n");
  622.         return 4;
  623.     case CONTENTS_CURRENT_180:
  624.         //Log("(current_180)\n");
  625.         return 5;
  626.     case CONTENTS_CURRENT_270:
  627.         //Log("(current_270)\n");
  628.         return 6;
  629.     case CONTENTS_CURRENT_UP:
  630.         //Log("(current_up)\n");
  631.         return 7;
  632.     case CONTENTS_CURRENT_DOWN:
  633.         //Log("(current_down)\n");
  634.         return 8;
  635.     case CONTENTS_SLIME:
  636.         //Log("(slime)\n");
  637.         return 9;
  638.     case CONTENTS_LAVA:
  639.         //Log("(lava)\n");
  640.         return 10;
  641.     case CONTENTS_SKY:
  642.         //Log("(sky)\n");
  643.         return 11;
  644.     case CONTENTS_SOLID:
  645.         //Log("(solid)\n");
  646.         return 12;
  647.  
  648. #ifdef ZHLT_DETAIL
  649.     case CONTENTS_DETAIL:
  650.         return 13;
  651.         //Log("(detail)\n");
  652. #endif
  653.  
  654.     default:
  655.         hlassert(false);
  656.         Error("RankForContents: bad contents %i", contents);
  657.     }
  658.     return -1;
  659. }
  660.  
  661. // =====================================================================================
  662. //  ContentsForRank
  663. // =====================================================================================
  664. static int      ContentsForRank(const int rank)
  665. {
  666.     switch (rank)
  667.     {
  668. #ifdef ZHLT_NULLTEX // AJM
  669.     case -2:
  670.         return CONTENTS_NULL;        // has at leat one face with null
  671. #endif
  672.  
  673.     case -1:
  674.         return CONTENTS_SOLID;                             // no faces at all
  675.     case 0:
  676.         return CONTENTS_EMPTY;
  677.     case 1:
  678.         return CONTENTS_WATER;
  679.     case 2:
  680.         return CONTENTS_TRANSLUCENT;
  681.     case 3:
  682.         return CONTENTS_CURRENT_0;
  683.     case 4:
  684.         return CONTENTS_CURRENT_90;
  685.     case 5:
  686.         return CONTENTS_CURRENT_180;
  687.     case 6:
  688.         return CONTENTS_CURRENT_270;
  689.     case 7:
  690.         return CONTENTS_CURRENT_UP;
  691.     case 8:
  692.         return CONTENTS_CURRENT_DOWN;
  693.     case 9:
  694.         return CONTENTS_SLIME;
  695.     case 10:
  696.         return CONTENTS_LAVA;
  697.     case 11:
  698.         return CONTENTS_SKY;
  699.     case 12:
  700.         return CONTENTS_SOLID;
  701.  
  702. #ifdef ZHLT_DETAIL // AJM
  703.     case 13:
  704.         return CONTENTS_DETAIL;
  705. #endif
  706.  
  707.     default:
  708.         hlassert(false);
  709.         Error("ContentsForRank: bad rank %i", rank);
  710.     }
  711.     return -1;
  712. }
  713.  
  714. // =====================================================================================
  715. //  FreeLeafSurfs
  716. // =====================================================================================
  717. static void     FreeLeafSurfs(node_t* leaf)
  718. {
  719.     surface_t*      surf;
  720.     surface_t*      snext;
  721.     face_t*         f;
  722.     face_t*         fnext;
  723.  
  724.     for (surf = leaf->surfaces; surf; surf = snext)
  725.     {
  726.         snext = surf->next;
  727.         for (f = surf->faces; f; f = fnext)
  728.         {
  729.             fnext = f->next;
  730.             FreeFace(f);
  731.         }
  732.         FreeSurface(surf);
  733.     }
  734.  
  735.     leaf->surfaces = NULL;
  736. }
  737.  
  738. // =====================================================================================
  739. //  LinkLeafFaces
  740. //      Determines the contents of the leaf and creates the final list of original faces 
  741. //      that have some fragment inside this leaf
  742. // =====================================================================================
  743. #define    MAX_LEAF_FACES    1024
  744.  
  745. static void     LinkLeafFaces(surface_t* planelist, node_t* leafnode)
  746. {
  747.     face_t*         f;
  748.     surface_t*      surf;
  749.     int             rank, r;
  750.     int             nummarkfaces;
  751.     face_t*         markfaces[MAX_LEAF_FACES];
  752.  
  753.     leafnode->faces = NULL;
  754.     leafnode->planenum = -1;
  755.  
  756.     rank = -1;
  757.     for (surf = planelist; surf; surf = surf->next)
  758.     {
  759.         for (f = surf->faces; f; f = f->next)
  760.         {
  761.             if ((f->contents == CONTENTS_HINT))
  762.             {
  763.                 f->contents = CONTENTS_EMPTY;
  764.             }
  765.             r = RankForContents(f->contents);
  766.             if (r > rank)
  767.             {
  768.                 rank = r;
  769.             }
  770.         }
  771.     }
  772.  
  773.     leafnode->contents = ContentsForRank(rank);
  774.  
  775.     if (leafnode->contents != CONTENTS_SOLID)
  776.     {
  777.         nummarkfaces = 0;
  778.         for (surf = leafnode->surfaces; surf; surf = surf->next)
  779.         {
  780.             for (f = surf->faces; f; f = f->next)
  781.             {
  782.                 hlassume(nummarkfaces < MAX_LEAF_FACES, assume_MAX_LEAF_FACES);
  783.  
  784.                 markfaces[nummarkfaces++] = f->original;
  785.             }
  786.         }
  787.  
  788.         markfaces[nummarkfaces] = NULL;                    // end marker
  789.         nummarkfaces++;
  790.  
  791.         leafnode->markfaces = (face_t**)malloc(nummarkfaces * sizeof(*leafnode->markfaces));
  792.         memcpy(leafnode->markfaces, markfaces, nummarkfaces * sizeof(*leafnode->markfaces));
  793.     }
  794.  
  795.     FreeLeafSurfs(leafnode);
  796.     leafnode->surfaces = NULL;
  797. }
  798.  
  799. // =====================================================================================
  800. //  MakeNodePortal
  801. //      Create the new portal by taking the full plane winding for the cutting plane and 
  802. //      clipping it by all of the planes from the other portals.
  803. //      Each portal tracks the node that created it, so unused nodes can be removed later.
  804. // =====================================================================================
  805. static void     MakeNodePortal(node_t* node)
  806. {
  807.     portal_t*       new_portal;
  808.     portal_t*       p;
  809.     dplane_t*       plane;
  810.     dplane_t        clipplane;
  811.     Winding *       w;
  812.     int             side = 0;
  813.  
  814.     plane = &g_dplanes[node->planenum];
  815.     w = new Winding(*plane);
  816.  
  817.     new_portal = AllocPortal();
  818.     new_portal->plane = *plane;
  819.     new_portal->onnode = node;
  820.  
  821.     for (p = node->portals; p; p = p->next[side])
  822.     {
  823.         clipplane = p->plane;
  824.         if (p->nodes[0] == node)
  825.         {
  826.             side = 0;
  827.         }
  828.         else if (p->nodes[1] == node)
  829.         {
  830.             clipplane.dist = -clipplane.dist;
  831.             VectorSubtract(vec3_origin, clipplane.normal, clipplane.normal);
  832.             side = 1;
  833.         }
  834.         else
  835.         {
  836.             Error("MakeNodePortal: mislinked portal");
  837.         }
  838.  
  839.         w->Clip(clipplane, true);
  840.         if (!w)
  841.         {
  842.             Warning("MakeNodePortal:new portal was clipped away from node@(%.0f,%.0f,%.0f)-(%.0f,%.0f,%.0f)",
  843.                     node->mins[0], node->mins[1], node->mins[2], node->maxs[0], node->maxs[1], node->maxs[2]);
  844.             FreePortal(new_portal);
  845.             return;
  846.         }
  847.     }
  848.  
  849.     new_portal->winding = w;
  850.     AddPortalToNodes(new_portal, node->children[0], node->children[1]);
  851. }
  852.  
  853. // =====================================================================================
  854. //  SplitNodePortals
  855. //      Move or split the portals that bound node so that the node's children have portals instead of node.
  856. // =====================================================================================
  857. static void     SplitNodePortals(node_t *node)
  858. {
  859.     portal_t*       p;
  860.     portal_t*       next_portal;
  861.     portal_t*       new_portal;
  862.     node_t*         f;
  863.     node_t*         b;
  864.     node_t*         other_node;
  865.     int             side = 0;
  866.     dplane_t*       plane;
  867.     Winding*        frontwinding;
  868.     Winding*        backwinding;
  869.  
  870.     plane = &g_dplanes[node->planenum];
  871.     f = node->children[0];
  872.     b = node->children[1];
  873.  
  874.     for (p = node->portals; p; p = next_portal)
  875.     {
  876.         if (p->nodes[0] == node)
  877.         {
  878.             side = 0;
  879.         }
  880.         else if (p->nodes[1] == node)
  881.         {
  882.             side = 1;
  883.         }
  884.         else
  885.         {
  886.             Error("SplitNodePortals: mislinked portal");
  887.         }
  888.         next_portal = p->next[side];
  889.  
  890.         other_node = p->nodes[!side];
  891.         RemovePortalFromNode(p, p->nodes[0]);
  892.         RemovePortalFromNode(p, p->nodes[1]);
  893.  
  894.         // cut the portal into two portals, one on each side of the cut plane
  895.         p->winding->Divide(*plane, &frontwinding, &backwinding);
  896.  
  897.         if (!frontwinding)
  898.         {
  899.             if (side == 0)
  900.             {
  901.                 AddPortalToNodes(p, b, other_node);
  902.             }
  903.             else
  904.             {
  905.                 AddPortalToNodes(p, other_node, b);
  906.             }
  907.             continue;
  908.         }
  909.         if (!backwinding)
  910.         {
  911.             if (side == 0)
  912.             {
  913.                 AddPortalToNodes(p, f, other_node);
  914.             }
  915.             else
  916.             {
  917.                 AddPortalToNodes(p, other_node, f);
  918.             }
  919.             continue;
  920.         }
  921.  
  922.         // the winding is split
  923.         new_portal = AllocPortal();
  924.         *new_portal = *p;
  925.         new_portal->winding = backwinding;
  926.         delete p->winding;
  927.         p->winding = frontwinding;
  928.  
  929.         if (side == 0)
  930.         {
  931.             AddPortalToNodes(p, f, other_node);
  932.             AddPortalToNodes(new_portal, b, other_node);
  933.         }
  934.         else
  935.         {
  936.             AddPortalToNodes(p, other_node, f);
  937.             AddPortalToNodes(new_portal, other_node, b);
  938.         }
  939.     }
  940.  
  941.     node->portals = NULL;
  942. }
  943.  
  944. // =====================================================================================
  945. //  CalcNodeBounds
  946. //      Determines the boundaries of a node by minmaxing all the portal points, whcih 
  947. //      completely enclose the node.
  948. //      Returns true if the node should be midsplit.(very large)
  949. // =====================================================================================
  950. static bool     CalcNodeBounds(node_t* node)
  951. {
  952.     int             i;
  953.     int             j;
  954.     vec_t           v;
  955.     portal_t*       p;
  956.     portal_t*       next_portal;
  957.     int             side = 0;
  958.  
  959.     node->mins[0] = node->mins[1] = node->mins[2] = 9999;
  960.     node->maxs[0] = node->maxs[1] = node->maxs[2] = -9999;
  961.  
  962.     for (p = node->portals; p; p = next_portal)
  963.     {
  964.         if (p->nodes[0] == node)
  965.         {
  966.             side = 0;
  967.         }
  968.         else if (p->nodes[1] == node)
  969.         {
  970.             side = 1;
  971.         }
  972.         else
  973.         {
  974.             Error("CalcNodeBounds: mislinked portal");
  975.         }
  976.         next_portal = p->next[side];
  977.  
  978.         for (i = 0; i < p->winding->m_NumPoints; i++)
  979.         {
  980.             for (j = 0; j < 3; j++)
  981.             {
  982.                 v = p->winding->m_Points[i][j];
  983.                 if (v < node->mins[j])
  984.                 {
  985.                     node->mins[j] = v;
  986.                 }
  987.                 if (v > node->maxs[j])
  988.                 {
  989.                     node->maxs[j] = v;
  990.                 }
  991.             }
  992.         }
  993.     }
  994.  
  995.     for (i = 0; i < 3; i++)
  996.     {
  997.         if (node->maxs[i] - node->mins[i] > g_maxnode_size)
  998.         {
  999.             return true;
  1000.         }
  1001.     }
  1002.     return false;
  1003. }
  1004.  
  1005. // =====================================================================================
  1006. //  CopyFacesToNode
  1007. //      Do a final merge attempt, then subdivide the faces to surface cache size if needed.
  1008. //      These are final faces that will be drawable in the game.
  1009. //      Copies of these faces are further chopped up into the leafs, but they will reference these originals.
  1010. // =====================================================================================
  1011. static void     CopyFacesToNode(node_t* node, surface_t* surf)
  1012. {
  1013.     face_t**        prevptr;
  1014.     face_t*         f;
  1015.     face_t*         newf;
  1016.  
  1017.     // merge as much as possible
  1018.     MergePlaneFaces(surf);
  1019.  
  1020.     // subdivide large faces
  1021.     prevptr = &surf->faces;
  1022.     while (1)
  1023.     {
  1024.         f = *prevptr;
  1025.         if (!f)
  1026.         {
  1027.             break;
  1028.         }
  1029.         SubdivideFace(f, prevptr);
  1030.         f = *prevptr;
  1031.         prevptr = &f->next;
  1032.     }
  1033.  
  1034.     // copy the faces to the node, and consider them the originals
  1035.     node->surfaces = NULL;
  1036.     node->faces = NULL;
  1037.     for (f = surf->faces; f; f = f->next)
  1038.     {
  1039.         if (f->contents != CONTENTS_SOLID)
  1040.         {
  1041.             newf = AllocFace();
  1042.             *newf = *f;
  1043.             f->original = newf;
  1044.             newf->next = node->faces;
  1045.             node->faces = newf;
  1046.         }
  1047.     }
  1048. }
  1049.  
  1050. // =====================================================================================
  1051. //  BuildBspTree_r
  1052. // =====================================================================================
  1053. static void     BuildBspTree_r(node_t* node)
  1054. {
  1055.     surface_t*      split;
  1056.     bool            midsplit;
  1057.     surface_t*      allsurfs;
  1058.  
  1059.     midsplit = CalcNodeBounds(node);
  1060.  
  1061.     split = SelectPartition(node->surfaces, node, midsplit);
  1062.     if (!split)
  1063.     {                                                      // this is a leaf node
  1064.         node->planenum = PLANENUM_LEAF;
  1065.         LinkLeafFaces(node->surfaces, node);
  1066.         return;
  1067.     }
  1068.  
  1069.     // these are final polygons
  1070.     split->onnode = node;                                  // can't use again
  1071.     allsurfs = node->surfaces;
  1072.     node->planenum = split->planenum;
  1073.     node->faces = NULL;
  1074.     CopyFacesToNode(node, split);
  1075.  
  1076.     node->children[0] = AllocNode();
  1077.     node->children[1] = AllocNode();
  1078.  
  1079.     // split all the polysurfaces into front and back lists
  1080.     SplitNodeSurfaces(allsurfs, node);
  1081.  
  1082.     // create the portal that seperates the two children
  1083.     MakeNodePortal(node);
  1084.  
  1085.     // carve the portals on the boundaries of the node
  1086.     SplitNodePortals(node);
  1087.  
  1088.     // recursively do the children
  1089.     BuildBspTree_r(node->children[0]);
  1090.     BuildBspTree_r(node->children[1]);
  1091. }
  1092.  
  1093. // =====================================================================================
  1094. //  SolidBSP
  1095. //      Takes a chain of surfaces plus a split type, and returns a bsp tree with faces 
  1096. //      off the nodes.
  1097. //      The original surface chain will be completely freed.
  1098. // =====================================================================================
  1099. node_t*         SolidBSP(const surfchain_t* const surfhead)
  1100. {
  1101.     node_t*         headnode;
  1102.  
  1103.     Verbose("----- SolidBSP -----\n");
  1104.  
  1105.     headnode = AllocNode();
  1106.     headnode->surfaces = surfhead->surfaces;
  1107.  
  1108.     if (!surfhead->surfaces)
  1109.     {
  1110.         // nothing at all to build
  1111.         headnode->planenum = -1;
  1112.         headnode->contents = CONTENTS_EMPTY;
  1113.         return headnode;
  1114.     }
  1115.  
  1116.     // generate six portals that enclose the entire world
  1117.     MakeHeadnodePortals(headnode, surfhead->mins, surfhead->maxs);
  1118.  
  1119.     // recursively partition everything
  1120.     BuildBspTree_r(headnode);
  1121.  
  1122.     return headnode;
  1123. }
  1124.